#ifndef __COMPONENT_CHASE_BEHAVIOR_H__
#define __COMPONENT_CHASE_BEHAVIOR_H__

#include "ComponentBehavior.hpp"
#include "Engine/MathUtils.hpp"
#include "EasyMachine.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentCreature;
    struct ComponentPathfinding;
    struct ComponentBody;
    struct ComponentAttacker;
    struct ComponentRandomFeedBehavior;

    class SubsystemBodies;
    class SubsystemGameInfo;
    class SubsystemTimeOfDay;
    class SubsystemNoise;


    struct ComponentChaseBehavior : public ComponentBehavior
    {
    protected:
        enum class MachineState
        {
            LookingForTarget,
            RandomMoving,
            Chasing
        };

        class StateMachine : public EasyMachine<MachineState>
        {
        protected:
            ComponentChaseBehavior * m_chaseBehavior;
        public:
            StateMachine(ComponentChaseBehavior *chaseBehavior);

            virtual void enter() override;
            virtual void update(float dt) override;
            virtual void leave() override;
        };

    protected:
        float m_importanceLevel;
        StateMachine *m_stateMachine;
        std::vector<ComponentBody*> m_componentBodies;


        double m_nextUpdateTime = 0.0f;
        bool m_isAttack = false;
        float m_attackPhase;

    public:
        ComponentCreature *componentCreature;
        ComponentPathfinding *componentPathfinding;
        ComponentAttacker *componentAttacker;
        ComponentRandomFeedBehavior *feedBehavior;

        SubsystemBodies *subsystemBodies;
        SubsystemGameInfo *subsystemGameInfo;
        SubsystemTimeOfDay *timeOfDay;
        SubsystemWeather *weather;
        SubsystemNoise *subsystemNoise;

        entt::entity targetEntity;

        float dayChaseRange;
        float nightChaseRange;
        float dayChaseTime;
        float nightChaseTime;
        float chaseNonPlayerProbability;
        float chaseWhenAttackedProbability;
        float chaseOnTouchProbability;
        uint8_t autoChaseMask;
        float targetUnsuitableTime;
        float targetInRangeTime;

        float range;
        float chaseTime;
        bool isPersistent;
        float autoChaseSuppressionTime;


        ComponentChaseBehavior() = default;
        ~ComponentChaseBehavior();

        virtual float getImportanceLevel() override;

        void attack(entt::entity entity, float maxRange, float maxChaseTime, bool persistent);

        ComponentCreature* findTarget();
        float scoreTarget(ComponentCreature* creature);
        bool isTargetInWater(ComponentBody *targetBody);

        bool isTargetInAttackRange(ComponentBody *targetBody);
        bool isBodyInAttackRange(ComponentBody *targetBody);
        ComponentBody *getHitBody(ComponentBody *targetBody, Vector3 &outHitPoint);


        constexpr static bool MultiThreadUpdate = true;
        static void Update(float dt);

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json &jsonData) override;
        virtual const std::string &getName() const override;
        static const std::string &GetName();
    };
}

#endif
